【SDOI2010】猪国杀题解

这个……真的是码农题中的码农题,真的写的我心态爆炸,所以来写一点东西造(bao)福(fu)社会。

其实没什么好说的(?)

首先是规则的理解方面。这玩意就是玩一盘三国杀,很多规则就自己理解了,读那个 $\text{SB}$ 题面根本就不可能打的对,当然我也讲不清楚。 所以说果然我还是三国杀玩的少了(雾)

然后有一个名叫类反贼的东西非常恶心。哪怕一个玩家是忠臣,只要用了一张 $\text{AOE}$ ,并且主公手里恰好没有可以抵消伤害的牌,那么这个可怜的忠臣就会被主公针对,除非他明示自己的身份。

然后就是无懈可击。这个是毒瘤中的毒瘤,因为无懈可击可以取消无懈可击,所以就会导致各种毒瘤事情,切莫打挂。

最后就是这些玩家的行为准则。这些玩家的行动相当的没有脑子,所以不能以常规的玩三国杀的思路来做,请注意。


如果你注意到了这些东西还没有过的话……恭喜你,可以开始调试了。

调试这种东西是 绝对不能 使用分步查看这种手段的,所以下面我简单地讲一下如何输出调试。

  1. 你的代码一般来说并不是很短,很多时候你的调试难易程度由你的代码决定,打代码时请务必三思 (这跟调试没什么关系吧喂!
  2. 输出调试时加上必要的标志信息,这样面对一大堆调试信息的时候也可以通过 Ctrl + F 来快速的寻找你所需要的关键信息
  3. 根据自己的需要写,哪里挂了在哪里加调试语句,这样有针对性的调试效率会高很多。
  4. 调试的时候应该模拟整局游戏的过程,比如说谁用了一张什么牌,谁杀了谁等等,比起只输出血量变化会有用的多
  5. 调试的时候请确认你已经熟悉了游戏规则。

大概就这些(吧),总之又是喜闻乐见的贴代码环节,由于调试语句的数量太多,所以删了(就是不给你们看.jpg),总之贴代码的目的只不过是给你们看一下曾经有这么一个人也写的很长罢了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
#include <bits/stdc++.h>
#define ri register int
#define il inline
#define ll long long
using namespace std;

const int N = 2e4 + 110;
const int MAXN = 110;
const int inf = 0x7fffffff;
const double eps = 1e-8;

il int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}
return x * f;
}

int n, m;
int Heap[N], top;
int tot[4];
bool End;

il int Card_Type(string s)
{
switch (s[0])
{
case 'P': return 1; break;
case 'K': return 2; break;
case 'D': return 3; break;
case 'F': return 4; break;
case 'N': return 5; break;
case 'W': return 6; break;
case 'J': return 7; break;
case 'Z': return 8; break;
}
}

il int Relationship(int stpa, int stpb)
{
if ((stpb == 3 && (stpa == 1 || stpa == 2)) ||
(stpa == 3 && (stpb == 1 || stpb == 2)))
return -1;
if ((stpa == 1 && stpb == 2) || (stpa == 2 && stpb == 1) ||
(stpa == 2 && stpb == 2) || (stpa == 3 && stpb == 3) || (stpa == 1 && stpb == 1))
return 1;
return 0;
}

struct player
{
int stp, num, hp; //stp : This pig's standpoint.
//num : The number of this pig's cards.
//hp : The remaining life of this pig.
int card[N];
int deem[12]; //This pig's impression of other pigs.
int tmp[N];
bool weapon;
bool idn; //Wether this pig is identified or not.

player()
{
num = stp = weapon = idn = 0;
memset(card, 0, sizeof(card));
deem[1] = 1;
hp = 4;
}

il void Get()
{
string s;
cin >> s;
switch (s[0])
{
case 'M': stp = 1, tot[1]++; break;
case 'Z': stp = 2, tot[2]++; break;
case 'F': stp = 3, tot[3]++; break;
}
for (ri i = 1; i <= 4; i++)
{
cin >> s;
card[++num] = Card_Type(s);
}
}

il void Clear()
{
weapon = hp = num = stp = idn = 0;
memset(card, 0, sizeof(card));
memset(tmp, 0, sizeof(tmp));
memset(deem, 0, sizeof(deem));
}

il bool Defend(int type)
{
for (ri i = 1; i <= num; i++)
if (card[i] == type)
{
card[i] = 0;
return 1;
}
return 0;
}

il void Get_One() //Get one card
{
if (top == m)
card[++num] = Heap[m];
else
card[++num] = Heap[++top];
}
il void Get_Card(int x) //Get x cards
{
for (ri i = 1; i <= x; i++)
Get_One();
}

il void Clear_Card() //Clear used cards
{
memset(tmp, 0, sizeof(tmp));
for (ri i = 1; i <= num; i++)
if (card[i] != 0)
tmp[++tmp[0]] = card[i];
num = tmp[0];
memset(card, 0, sizeof(card));
for (ri i = 1; i <= num; i++)
card[i] = tmp[i];
}
};
player a[12];

il void print(int winner)
{
if (winner == 1)
puts("MP");
else
puts("FP");
for (ri i = 1; i <= n; i++)
{
if (!a[i].hp)
puts("DEAD");
else
{
a[i].Clear_Card();
for (ri j = 1; j <= a[i].num; j++)
{
switch (a[i].card[j])
{
case 1: putchar('P'); break;
case 2: putchar('K'); break;
case 3: putchar('D'); break;
case 4: putchar('F'); break;
case 5: putchar('N'); break;
case 6: putchar('W'); break;
case 7: putchar('J'); break;
case 8: putchar('Z'); break;
}
putchar(' ');
}
putchar('\n');
}
}
exit(0);
}

il int Check_End()
{
if (!a[1].hp)
{
End = 1;
print(3);
return 3;
}
for (ri i = 1; i <= n; i++)
if (a[i].stp == 3 && a[i].hp)
return 0;
print(1);
return 1;
}

il void Liquidation(int from, int id)
{
if (a[id].stp == 2 && from == 1)
{
memset(a[1].card, 0, sizeof(a[1].card));
memset(a[1].tmp, 0, sizeof(a[1].tmp));
a[1].num = 0;
a[1].weapon = 0;
}
else if (a[id].stp == 3)
a[from].Get_Card(3);
}

il void Death_Check(int from, int id) //Wether this pig will die or not
{
a[id].hp--;
if (a[id].hp > 0)
return;
for (ri i = 1; i <= a[id].num; i++)
if (a[id].card[i] == 1)
{
a[id].hp++;
a[id].card[i] = 0;
return;
}
if (!Check_End())
Liquidation(from, id);
a[id].Clear();
}

il bool Decide(int from) //Decide who to use this Slash
{
int dis = 0;
bool Slash = 0;
for (ri i = from % n + 1; i != from; i = i % n + 1)
{
if (!a[i].hp)
continue;
dis = 1;
if (from == 1 && !a[i].idn && Relationship(a[from].stp, a[from].deem[i]) == -1)
{
Slash = 1;
if (!a[i].Defend(3))
Death_Check(from, i);
a[from].idn = 1;
}
else if (a[i].idn && Relationship(a[from].stp, a[i].stp) == -1)
{
Slash = 1;
if (!a[i].Defend(3))
Death_Check(from, i);
a[from].idn = 1;
}
if (dis)
break;
}
return Slash;
}

il bool Check(int from, int now) //Check wether this card will come into force
{
bool enable = 1;
int i = from, k = 0;
while (k < n)
{
if (i != 1)
{
if (!a[now].idn)
break;
if (Relationship(a[i].stp, a[now].stp) == 1 && enable ||
Relationship(a[i].stp, a[now].stp) == -1 && !enable || (i == now && enable))
{
for (ri j = 1; j <= a[i].num; j++)
if (a[i].card[j] == 7)
{
a[i].card[j] = 0;
enable ^= 1;
a[i].idn = 1;
k = 0;
break;
}
}
}
else
{
if ((a[now].idn && (a[now].stp == 3 && !enable || a[now].stp == 2 && enable)) ||
(i == now && enable) || !a[now].idn && a[1].deem[now] == 3)
{
for (ri j = 1; j <= a[i].num; j++)
if (a[i].card[j] == 7)
{
a[i].card[j] = 0;
enable ^= 1;
k = 0;
break;
}
}
}
i = i % n + 1;
k++;
}
return enable;
}

il void Duel(int x, int y) //x------Duel------>y
{
if (x == 1 && a[y].stp == 2)
{
Death_Check(x, y);
return;
}
while (1)
{
bool bar = 0;
for (ri i = 1; i <= a[y].num; i++)
if (a[y].card[i] == 2)
{
bar = 1;
a[y].card[i] = 0;
break;
}
if (!bar)
{
Death_Check(x, y);
return;
}

bool foo = 0;
for (ri i = 1; i <= a[x].num; i++)
if (a[x].card[i] == 2)
{
foo = 1;
a[x].card[i] = 0;
break;
}
if (!foo)
{
Death_Check(y, x);
return;
}
}
}

il bool Lord_Check_Duel()
{
bool foo = 0;
for (ri i = 2; i <= n; i++)
{
if (!a[i].hp)
continue;
if (a[i].idn && a[i].stp == 3 || !a[i].idn && a[1].deem[i] == 3)
{
if (Check(1, i))
Duel(1, i);
foo = 1;
break;
}
}
return foo;
}
il bool Loyal_Check_Duel(int id)
{
bool foo = 0;
for (ri i = id % n + 1; i != id; i = i % n + 1)
{
if (!a[i].hp)
continue;
if (a[i].idn && a[i].stp == 3)
{
if (Check(id, i))
Duel(id, i);
foo = 1;
break;
}
}
return foo;
}
il bool Check_Duel(int id)
{
switch (a[id].stp)
{
case 1: return Lord_Check_Duel(); break;
case 2: return Loyal_Check_Duel(id); break;
case 3: if (Check(id, 1)) Duel(id, 1); return 1; break;
}
}

il void AOE(int from, int type) //Use an AOE
{
for (ri i = from % n + 1; i != from; i = i % n + 1)
{
if (!a[i].hp)
continue;
if (!Check(from, i))
continue;
if (!a[i].Defend(type))
{
Death_Check(from, i);
if (!a[from].idn && i == 1)
a[i].deem[from] = 3;
}
}
}

il void Use_Card(int id)
{
bool foo = 0;
for (ri i = 1; i <= a[id].num; i++)
{
if (!a[id].card[i])
continue;
if (a[id].hp < 4 && a[id].card[i] == 1)
{
a[id].hp++;
a[id].card[i] = 0;
continue;
}
if (!foo && a[id].card[i] == 2)
{
a[id].card[i] = 0;
if (Decide(id))
{
if (!a[id].weapon)
foo = 1;
i = 0;
}
else
a[id].card[i] = 2;
continue;
}
if (a[id].card[i] == 4)
{
a[id].card[i] = 0;
if (Check_Duel(id))
{
a[id].idn = 1;
i = 0;
}
else
a[id].card[i] = 4;
continue;
}
if (a[id].card[i] == 5)
{
a[id].card[i] = 0;
AOE(id, 2);
i = 0;
continue;
}
if (a[id].card[i] == 6)
{
a[id].card[i] = 0;
AOE(id, 3);
i = 0;
continue;
}
if (a[id].card[i] == 8)
{
a[id].weapon = 1;
a[id].card[i] = 0;
foo = 0;
i = 0;
continue;
}
}
}

il void Game_Start()
{
while (!End)
{
for (ri i = 1; i <= n; i++)
{
if (!a[i].hp)
continue;
a[i].Get_Card(2);
Use_Card(i);
a[i].Clear_Card();
}
}
}

int main()
{
n = read(), m = read();
for (ri i = 1; i <= n; i++)
a[i].Get();
for (ri i = 1; i <= m; i++)
{
string s;
cin >> s;
Heap[i] = Card_Type(s);
}
a[1].idn = 1;
Game_Start();
return 0;
}
/*
3 10
MP D D F F
ZP N N N D
FP J J J J
F F D D J J F F K D

*/
0%